package edu.core.testapp.server;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;

import javax.xml.bind.DatatypeConverter;

import protect02.CloseKey;
import protect02.OpenKey;
import protect02.RSA;
import protect02.RSAKeys;

import com.google.cloud.sql.jdbc.internal.DataTypeConverter;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import edu.core.testapp.client.Protect02Service;
import edu.core.testapp.client.Protect02ServiceAsync;
import edu.core.testapp.shared.RSAKeysString;
import edu.core.testapp.shared.RSAKeysString.RSACLoseKeyString;
import edu.core.testapp.shared.RSAKeysString.RSAOpenKeyString;

@SuppressWarnings("serial")
public class Protect02ServiceImpl extends RemoteServiceServlet  implements Protect02Service {

	@Override
	public String[] getnerateKeys() {
		
		String[] result = new String[3];
		
		RSAKeysString keys = generateKeys();
		
		result[0] = keys.getOpen().getE();
		result[1] = keys.getOpen().getN();
		result[2] = keys.getClose().getD();
		
		return result;
	}

	@Override
	public RSAKeysString generateKeys() {
		
		RSAKeys keys = RSA.generateKeys();
		RSAOpenKeyString open = new RSAOpenKeyString(keys.getOK().getE().toString(), keys.getOK().getN().toString());
		RSACLoseKeyString close = new RSACLoseKeyString(keys.getCK().getD().toString());
		
		RSAKeysString result = new RSAKeysString(open, close);
		
		return result;
	}

	@Override
	public String encodeString(String msg, RSAOpenKeyString open) throws IOException {
		String result = "";
		
		OpenKey ok = new OpenKey(new BigInteger(open.getE()), new BigInteger(open.getN()));
		
		ByteArrayInputStream bais = new ByteArrayInputStream(msg.getBytes()); 
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		RSA.encode(bais, baos, ok);
		
		result = new String(baos.toByteArray());
		
		return result;
	}

	@Override
	public String decodeString(String code, RSAOpenKeyString open,
			RSACLoseKeyString close) throws IOException {
		String result = "";
		
		OpenKey ok = new OpenKey(new BigInteger(open.getE()), new BigInteger(open.getN()));
		CloseKey ck = new CloseKey(new BigInteger(close.getD()));
		
		ByteArrayInputStream bais = new ByteArrayInputStream(code.getBytes());
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		RSA.decode(bais, baos, ok, ck);
		
		result = new String(baos.toByteArray());
		
		return result;
	}

	@Override
	public String stringToBase64(String string) throws UnsupportedEncodingException {
		// TODO Auto-generated method stub
		byte[] buf = string.getBytes("UTF-16");
		String result = DatatypeConverter.printBase64Binary(buf);
		return result;
	}

	@Override
	public String base64ToString(String base64) throws UnsupportedEncodingException {
		// TODO Auto-generated method stub
		byte[] buf = DatatypeConverter.parseBase64Binary(base64);
		String result = new String(buf, "UTF-16");
		return result;
	}

	@Override
	public String encodeBase64(String msg, RSAOpenKeyString open)
			throws IOException {
		// TODO Auto-generated method stub
		byte[] buf = DatatypeConverter.parseBase64Binary(msg);
		
		OpenKey ok = new OpenKey(new BigInteger(open.getE()), new BigInteger(open.getN()));
		
		ByteArrayInputStream bais = new ByteArrayInputStream(buf); 
		ByteArrayOutputStream baos = new ByteArrayOutputStream();

		RSA.encode(bais, baos, ok);
		
		String result = DatatypeConverter.printBase64Binary(baos.toByteArray());
		
		return result;
	}

	@Override
	public String decodeBase64(String code, RSAOpenKeyString open,
			RSACLoseKeyString close) throws IOException {
		// TODO Auto-generated method stub
		byte[] buf = DatatypeConverter.parseBase64Binary(code);
		
		OpenKey ok = new OpenKey(new BigInteger(open.getE()), new BigInteger(open.getN()));
		CloseKey ck = new CloseKey(new BigInteger(close.getD()));
		
		ByteArrayInputStream bais = new ByteArrayInputStream(buf);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		RSA.decode(bais, baos, ok, ck);
		
		String result = DatatypeConverter.printBase64Binary(baos.toByteArray());
		
		return result;
	}

}
